package jupiter.channel;
import org.json.*;



import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import jupiter.filters.FilterException;
public class List {
	
	class Unit {
		public JSONObject data;
		public int count;
		public Hashtable<String, JSONObject> sessionDataHash;
		Unit(JSONObject d){
			data=  d;
			count = 0;  //this is a count for the number of JabbifyNodes
			sessionDataHash = new Hashtable<String, JSONObject>();
		}
		
	}
	
	Address address;
	private Hashtable<String, Unit> subscribers= new  Hashtable<String, Unit>();
	List(Address a){
		address = a;
	}
	public Address getAddress(JSONObject data) throws FilterException {
		try{
			return new Address(data.getString("address"));
		}catch(JSONException e){
			throw new FilterException("{error: 'cant find address'}");
		}
	}
	
	
	public int addData(JSONObject data)throws FilterException {
		Address add = getAddress(data);

		int length;
		synchronized (subscribers) {
			if(subscribers.containsKey(add.toString())){
				subscribers.get(add.toString()).count++;
			}else{
				subscribers.put(add.toString(), new Unit(data));
			}
			length = subscribers.size();
		}
		return length;
	}
	/**
	 * Only updates if there, possible you do an update on a channel no one is listening to
	 * @param data
	 */
	public void updateData(JSONObject data)throws FilterException {
		
		Address add = getAddress(data);
//		System.out.println("~ "+address+" with "+add.toString()+"'s data = "+data);
		synchronized (subscribers) {
//			System.out.println("  Size = "+subscribers.size()+ " "+ toString());
			if(subscribers.containsKey(add.toString())){
				subscribers.get(add.toString()).data = data;
			}else{
				System.out.println(" Couldn't find address "+add);
			}
		}
	}
	public int removeData(JSONObject data)throws FilterException {
		
		Address add = getAddress(data);
		int length;
		synchronized (subscribers) { //only remove if 0
			int num = subscribers.get(add.toString()).count--;
			if(num ==0){
				System.out.println("- "+add+" from "+address.toString());
				subscribers.remove(add.toString());
			}
			length = subscribers.size();
		}
		return length;
	}
	//basically, this should go through each address in subscribers and check for more info
	public ArrayList<JSONObject> getList(){
		//System.out.println("  Getting list from "+address.toString());
		ArrayList<JSONObject> list = new ArrayList<JSONObject>();
		synchronized (subscribers) {
			//System.out.println( "  Size = "+ subscribers.size());
			for(Iterator<Map.Entry <String, Unit>> iter = subscribers.entrySet().iterator(); iter.hasNext();){
				list.add(iter.next().getValue().data);
			}
		}
		return list;
	}
	public String toString(){
		String str = "";
		synchronized (subscribers) {
			for(Iterator<Map.Entry <String, Unit>> iter = subscribers.entrySet().iterator(); iter.hasNext();){
				str += iter.next().getKey() + " ";
			}
		}
		return str;
	}
	
	public int getCount() throws FilterException {
		synchronized (subscribers) {
			System.out.println("Size: "+toString());
			return subscribers.size();
		}
	}
	
	
	
}
